package set

import (
	"fmt"
	"strings"
)

type Set struct {
	xs [9]bool
}

var Empty Set = Set{}

func NewSet(x ...int) Set {
	result := Set{}
	for _, i := range x {
		result.xs[i] = true
	}
	return result
}

func NewFull() Set {
	result := Set{}
	for i := range result.xs {
		result.xs[i] = true
	}
	return result
}

func (s *Set) Full() {
	for i := range s.xs {
		s.xs[i] = true
	}
}

func (s *Set) Empty() {
	for i := range s.xs {
		s.xs[i] = false
	}
}

func (s Set) IsNull() bool {
	for _, x := range s.xs {
		if x {
			return false
		}
	}
	return true
}
func (s *Set) Add(i int) bool {
	if s.xs[i] {
		return false
	}
	s.xs[i] = true
	return true
}

func (s *Set) Delete(i int) bool {
	if !s.xs[i] {
		return false
	}
	s.xs[i] = false
	return true
}

func (s *Set) DeleteAll(other Set) bool {
	b := false
	for i, x := range other.xs {
		if x && s.Delete(i) {
			b = true
		}
	}
	return b
}

func (s *Set) RemoveAllBut(other Set) bool {
	b := false
	for i, x := range s.xs {
		if x && !other.xs[i] {
			s.xs[i] = false
			b = true
		}
	}
	return b
}
func (s Set) Has(i int) bool {
	return s.xs[i]
}

func (s Set) HasAny(other Set) bool {
	for i, x := range other.xs {
		if x && s.xs[i] {
			return true
		}
	}
	return false
}

/*
	func (s Set) Equal(other Set) bool {
		for i, x := range s.xs {
			if x != other.xs[i] {
				return false
			}
		}
		return true
	}
*/
func (s Set) IsSuperset(subset Set) bool {
	for i, x := range subset.xs {
		if x && !s.xs[i] {
			return false
		}
	}
	return true
}
func (s Set) Count() int {
	count := 0
	for _, x := range s.xs {
		if x {
			count++
		}
	}
	return count
}

func (s Set) GetList() []int {
	results := make([]int, 0, 9)
	for i, x := range s.xs {
		if x {
			results = append(results, i)
		}
	}
	return results
}

func (s *Set) SetList(is []int) {
	s.Empty()
	for _, i := range is {
		s.xs[i] = true
	}
}

func (s Set) Intersect(other Set) Set {
	result := NewSet()
	for i, x := range s.xs {
		if x && other.xs[i] {
			result.xs[i] = true
		}
	}
	return result
}

func (s Set) Union(other Set) Set {
	result := NewSet()
	for i, x := range s.xs {
		if x || other.xs[i] {
			result.xs[i] = true
		}
	}
	return result
}
func (s Set) Complement() Set {
	result := NewSet()
	for i, x := range s.xs {
		if !x {
			result.xs[i] = true
		}
	}
	return result
}

func (s Set) Diff(other Set) Set {
	result := NewSet()
	for i, x := range s.xs {
		if x && !other.xs[i] {
			result.xs[i] = true
		}
	}
	return result
}

func (s Set) SymDiff(other Set) Set {
	result := NewSet()
	for i, x := range s.xs {
		if x != other.xs[i] {
			result.xs[i] = true
		}
	}
	return result
}

func (s Set) String() string {
	var b strings.Builder
	for i, x := range s.xs {
		if x {
			fmt.Fprintf(&b, "%d", i)
		}
	}
	return b.String()
}

func (s Set) ValueString() string {
	var b strings.Builder
	for i, x := range s.xs {
		if x {
			fmt.Fprintf(&b, "%d", i+1)
		}
	}
	return b.String()
}
